package org.lexicon.swpogo
import com.hp.hpl.jena.rdf.model.Model;
import com.hp.hpl.jena.rdf.model.ModelFactory;
import com.hp.hpl.jena.shared.PrefixMapping;
import com.hp.hpl.jena.rdf.model.Resource;
import com.hp.hpl.jena.rdf.model.Property;
import groovy.util.logging.Log

@Log
public class RdfBuilder extends BuilderSupport {

	Model rdfmodel
	Resource subject
	com.hp.hpl.jena.rdf.model.Property predicate
	
	def rdfType = {
		if (this.rdfmodel.getNsPrefixMap().containsKey(rdf)) {
			this.rdfmodel.createProperty(this.rdfmodel.getNsPrefixURI("rdf"))
		}
		else {
			this.rdfmodel.createProperty("http://www.w3.org/1999/02/22-rdf-syntax-ns#type")
		}
	}
	
	public void createModel() {
		this.rdfmodel = ModelFactory.createDefaultModel()
	}
	
	public void createModel(Map prefixes) {
		this.createModel()
		this.rdfmodel.setNsPrefixes(prefixes)
	} 
	
	public String uriResolver (String uri) throws UndeclaredRdfBuilderNamespaceException  {
		if (uri =~ /^http:/) {
			return "test"
		}
		else if (this.rdfmodel.getNsPrefixURI(uri.split(":")[0])) {
			throw new UndeclaredRdfBuilderNamespaceException("Undeclared namespace in RdfBuilder instance for '${uri.split("":"")[0]}'")
		}
		else {
			return this.rdfmodel.getNsPrefixURI(uri.split(":")[0]) +  uri.split(":")[1]
		}
	}
		
	public Resource createResource(String uri) throws RdfBuilderException {
		try {
			return this.rdfmodel.createResource(uri)
		}
		catch (UndeclaredRdfBuilderNamespaceException e) {
			throw e
		}
		catch (Exception e) {
			throw new RdfBuilderException(e)
		}
	} 
	
	public Resource createResource() {
		return this.rdfmodel.createResource()
	}
	
	public com.hp.hpl.jena.rdf.model.Property createProperty(String uri) throws RdfBuilderException {
		try {
			return this.rdfmodel.createProperty(uri)
		}
		catch (UndeclaredRdfBuilderNamespaceException e) {
			throw e
		}
		catch (Exception e) {
			throw new RdfBuilderException(e)
		}
	}
	
	protected void setParent(Object parent, Object child) {
		switch (parent) {
			case Resource:
				this.subject = parent
				this.predicate = child
				break
			
			case com.hp.hpl.jena.rdf.model.Property:
				switch (child) {
					case Resource:
						this.rdfmodel.add(this.rdfmodel.createStatement(this.subject, this.predicate, child))
						break
				
					default:
						this.rdfmodel.add(this.rdfmodel.createStatement(this.subject, this.predicate, this.rdfmodel.createTypedLiteral(child)))
						break
				}
				break
			
			default:
				break
		}
	}
	
	protected Object createNode(Object name) {
		println "create 1 arg node: ${name.toString()} \n"
		return [:]
	}
	
	protected Object createNode(Object name, Object value) {
		this.createNode(name, [uri:value])
	}
	
	protected Object createNode(Object name, Map attributes) {
		switch (name) {
			case "Resource":
				return this.createResource()
				break
			case "Predicate":
				return this.createProperty(attributes.get("uri").toString())
				break
			case "Model":
				return this.createNode(name, [value])
				break
			default:
			break
		}
	}
	
	protected Object createNode(Object name, Map attributes, Object value) {
		println "setting 3 arg node: ${name.toString()}, ${attributes.toString()}, ${value.toString()} \n"
		return [:]
	}
	
	protected doInvokeMethod(String methodName, Object name, Object args) {
		println "calling ${methodName}, with ${name.toString()} and ${args.toString()}"
		super.doInvokeMethod(methodName, name, args)
	}

}
